package com.luobd.bpm.activiti;

import org.activiti.bpmn.model.FlowElement;
import org.activiti.bpmn.model.Process;
import org.activiti.bpmn.model.StartEvent;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.delegate.event.ActivitiEventType;
import org.activiti.engine.delegate.event.impl.ActivitiEventBuilder;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.interceptor.CommandContext;
import org.activiti.engine.impl.persistence.entity.ExecutionEntity;
import org.activiti.engine.impl.persistence.entity.ExecutionEntityManager;
import org.activiti.engine.impl.util.ProcessDefinitionUtil;
import org.activiti.engine.impl.util.ProcessInstanceHelper;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;

import java.util.Map;

public class CustomProcessInstanceHelper extends ProcessInstanceHelper {

    public ProcessInstance createAndStartProcessInstance(String processInstanceId,ProcessDefinition processDefinition, String businessKey, String processInstanceName, Map<String, Object> variables, Map<String, Object> transientVariables, boolean startProcessInstance) {
        if(ProcessDefinitionUtil.isProcessDefinitionSuspended(processDefinition.getId())) {
            throw new ActivitiException("名称为: " + processDefinition.getName() + ",编号为" + processDefinition.getId() + "的流程已挂起" );
        }

        Process process = ProcessDefinitionUtil.getProcess(processDefinition.getId());

        if(process == null) {
            throw new ActivitiException("名称为" + processDefinition.getName() + ",编号为" + processDefinition.getId() + "的流程定义没有process元素,无法发起");
        }

        FlowElement initialFlowElement = process.getInitialFlowElement();
        if (initialFlowElement == null) {
            throw new ActivitiException("编号为" + processDefinition.getId() + "没有开始事件。");
        }
        return createAndStartProcessInstanceWithInitialFlowElement(processDefinition,
                processInstanceId, businessKey,
                processInstanceName, initialFlowElement, process, variables,
                transientVariables, startProcessInstance);

    }


    public ProcessInstance createAndStartProcessInstanceWithInitialFlowElement
            (ProcessDefinition processDefinition, String processInstanceId, String businessKey,
             String processInstanceName, FlowElement initialFlowElement, Process process,
             Map<String, Object> variables, Map<String, Object> transientVariables, boolean
                     startProcessInstance) {
        CommandContext commandContext = Context.getCommandContext();
        //创建流程实例
        String initiatorVariableName = null;
        if (initialFlowElement instanceof StartEvent) {
            initiatorVariableName = ((StartEvent) initialFlowElement).getInitiator();
        }

        CustomExecutionEntityManager executionEntityManager = (CustomExecutionEntityManager) commandContext.getExecutionEntityManager();
        //调用自定义Execution实体管理器创建流程实例
        ExecutionEntity processInstance = executionEntityManager.createProcessInstanceExecution(processDefinition,
                processInstanceId, businessKey, processDefinition.getTenantId(),
                initiatorVariableName);
        //记录流程历史
        commandContext.getHistoryManager()
                .recordProcessInstanceStart(processInstance, initialFlowElement);
        processInstance.setVariables(processDataObjects(process.getDataObjects()));
        //设置流程变量
        if (variables != null) {
            for (String varName : variables.keySet()) {
                processInstance.setVariable(varName, variables.get(varName));
            }
        }
        if (transientVariables != null) {
            for (String varName : transientVariables.keySet()) {
                processInstance.setTransientVariable(varName, transientVariables.get(varName));
            }
        }
        //设置流程名称
        if (processInstanceName != null) {
            processInstance.setName(processInstanceName);
            commandContext.getHistoryManager()
                    .recordProcessInstanceNameChange(processInstance.getId(), processInstanceName);
        }
        //发送事件
        if (Context.getProcessEngineConfiguration().getEventDispatcher().isEnabled()) {
            Context.getProcessEngineConfiguration().getEventDispatcher()
                    .dispatchEvent(ActivitiEventBuilder.createEntityWithVariablesEvent
                    (ActivitiEventType.ENTITY_INITIALIZED, processInstance, variables, false));
        }
        //创建第一个执行实例
        ExecutionEntity execution =
                commandContext.getExecutionEntityManager().createChildExecution(processInstance);
        execution.setCurrentFlowElement(initialFlowElement);
        if (startProcessInstance) {
            startProcessInstance(processInstance, commandContext, variables);
        }
        return processInstance;
    }


}
